package de.unimannheim.ki.usermanagement;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;

import de.unimannheim.ki.servlets.MainServer;
import de.unimannheim.ki.servlets.WebServiceClient;




public class FacebookSessionHandler {
	// test servlet
	//public static String APPADRESS = "/my-music-search/test";
	
	// standard servlet
	public static String APPADRESS = "/start";
	
	public static String APPADRESSShort = "";
	
	//test APPID
		//public static String APPID = "463222877063244";
		//public static String APPSECRET = "f85c6b72a6def06af5cf531609205a58";
		
	//standard APPID
	//public static String APPID = "146091488853683";
	//public static String APPSECRET = "bcf4c7f2dc48eb2805de71514c1b7443";
	
	//final APPID
	public static String APPID = "278262065628336";
	public static String APPSECRET = "a20f754f232f2fd37b4783e409d976bd";
	
	private Gson gson;
	private Map<String,String> userMap;
	private String useraccessToken; 
	public FacebookSessionHandler() {
		super();
		this.userMap = new HashMap<String, String>();
		gson = new Gson();
	}
	
	public void loguserout(String adress){
		userMap.remove(adress);
	}
	
	public boolean userisRegistered(String adress){
		return userMap.containsKey(adress);
	}
	public void userAddRegistry(String adress){
		userMap.put(adress, null);
	}
	
	public boolean userisLoggedIn(HttpSession session){
		return session.getAttribute(MainServer.SESSIONATTRI)!= null;
		
	}
	
	public String getAccessToken(HttpSession session){
		return (String) session.getAttribute(MainServer.SESSIONATTRI);
	}
	
	public void handleLogFlow(HttpSession session, String serveradress, String serverport, String adress, HttpServletResponse response, WebServiceClient wsClient, Map<String, String[]> paramMap) throws IOException{
		if(! userisRegistered(adress)){
			userAddRegistry(adress);
			this.handleLogFlow(session, serveradress, serverport, adress, response, wsClient, paramMap);
		}else{
			//handle request
			if(userisLoggedIn(session)){
				return;
			}else{
				if(!paramMap.containsKey("access_token")){
					if(paramMap.containsKey("state")){
						if(paramMap.containsKey("error")){
							//user don't want to use the app
							//do some processing!
						}else{
							InputStream tokenstream = null;
							String code = paramMap.get("code")[0];
					//finalize request
							String url = "https://graph.facebook.com/oauth/access_token?"+
									"client_id="+APPID+
									"&redirect_uri=http://"+serveradress+":"+serverport+APPADRESS+
									"&client_secret="+APPSECRET+
									"&code="+code
									;
							try {
								tokenstream =  wsClient.perfomSynchCall(url);
							} catch (Exception e) {
								e.printStackTrace();
							}
					 
			
						
							BufferedReader breader = new BufferedReader( new InputStreamReader(tokenstream));
					
							String line = null;
							String splitter[] = null;
					 		while( ( line = breader.readLine()) != null){
					 				
					 				splitter =  line.split("=");
					 		}
					 			
					 		breader.close();
					 		String accessToken = null;
					 		try{
					 		 accessToken = splitter[1].substring(0, splitter[1].indexOf('&'));
					 		} catch (Exception e){
					 			String message = "";
					 			for (String string : splitter) {
									message = message + "+" + string;
								}
					 			try {
									throw new Exception (message);
								} catch (Exception e1) {
									// TODO Auto-generated catch block
									e1.printStackTrace();
								}
					 			e.printStackTrace();
					 		}
					 		// get FB ID
					 		FbUser fb = this.doFQLQuery(accessToken, wsClient, this.buildQueryStringGetFBID()).get(0);
					 		
					 		session.setAttribute(MainServer.SESSIONATTRI, accessToken);
					 		session.setAttribute(MainServer.FBUSER,fb.uid);
					 		//userMap.put(adress, accessToken);
					 		useraccessToken = accessToken;
					 		
					 	
					 		response.sendRedirect("http://"+serveradress+":"+serverport+APPADRESS);
					 		
							}
				
					} else {
						String redirectstringforoauth ="https://www.facebook.com/dialog/oauth?"+
								"client_id="+APPID+
								"&redirect_uri=http://"+serveradress+":"+serverport+APPADRESS+"?"+
								"&scope=user_likes, friends_likes "+
								"&state=login"+adress;
						response.sendRedirect(redirectstringforoauth);
					}//else
				}
			}
		}
	}//method
	
	public String buildQueryString(){
		String basicquery = "SELECT uid, name, pic_square, music, books, movies, tv FROM user WHERE uid IN (SELECT uid2 FROM friend WHERE uid1 = me())";
		return basicquery;
	}
	
	public String buildQueryStringGetFBID(){
		String basicquery = "SELECT uid, first_name, last_name, pic_square, music, books, movies, tv FROM user WHERE uid= me()";
		return basicquery;
	}
	
	
	public String buildQueryString(String userid){
		String basicquery = "SELECT uid, first_name, last_name, pic_square, music, books, movies, tv FROM user WHERE uid= "+userid+"";
		return basicquery;
	}
	
	public List<FbUser> doFQLQuery(String acessToken, WebServiceClient wsClient, String query){
		List<FbUser> userlist  = null;
		InputStream stream;

		 try {
			 //perform JQL Query
			  stream = wsClient.performQuery(query,  acessToken);
			  JsonParser parser = new JsonParser();
			  // get Json String
			  JsonObject obj = parser.parse(new InputStreamReader(stream)).getAsJsonObject();
			  JsonElement elem = obj.get("data");
		
			  //parse Json String with gson Library
			  userlist =  gson.fromJson(elem.toString(), new TypeToken<List<FbUser>>(){}.getType());

		} catch (Exception e) {
		 e.printStackTrace();
		}
	
		 return userlist;
		 
	}
	
	
}
